#ifndef BROWSEFOLDERDIALOG_H_97B5E754_8072_4B62_8278_410436D5A2D8
#define BROWSEFOLDERDIALOG_H_97B5E754_8072_4B62_8278_410436D5A2D8
/**
 * \file BrowseFolderDialog.h
 *
 * \brief Header file for class CBrowseFolderDialog
 *
 * $Id: BrowseFolderDialog.h,v 1.4 2003/07/11 20:22:25 mgh Exp $
 *
 *
 * Copyright (C) 2003 Michael G. Herstine <sp1ff@pobox.com>
 *
 * Permission to use, copy, or  modify this source code is hereby
 * granted free  of charge,  provided that this  copyright notice
 * appear on all copies and  on all source code derived from this
 * code.  No representation is  made regarding the suitability of
 * this software for any purpose.  It is provided "as is" without
 * express or implied warranty.
 *
 *
 */


#ifndef STDAFX_H_A6207C03_3B23_4823_BC30_4088F15F3A93
//# error "You must include 'StdAfx.h' before this file for PCH!"
#endif  // not StdAfx.h


/**
 * \class CBrowseFolderDialog
 *
 * \brief MFC Dialog wrapping \c ::SHBrowseForFolder
 *
 *
 * CBrowseFolderDialog implements a different approach to wrapping \c
 * SHBrowseForFolder in an MFC-friendly way.  It actually
 * subclasses \c CWnd, allowing you to hook into the MFC Message
 * Mapping mechanism for customization.  Naturally, it also takes
 * care of some unpleasant chores associated with with \c
 * SHBrowseForFolder, such as translating from an \c LPITEMIDLIST
 * to a CString, and so on.
 *
 * Use it just like you would any other MFC-based Dialog:
 *
 \code
   void CMyClass::CMyHandler()
   {
     YABFFW dlg(_T("Choose a folder"), BIF_USENEWUI, this,
                CSIDL_DESKTOP);
     if (IDOK == dlg.DoModal())
     {
       CString s = dlg.GetPath();
       // Do something with `s' ...
     }
 \endcode
 *
 *
 */

class CBrowseFolderDialog : public CWnd
{
  // Construction
public:
  /// Construct a CBrowseFolderDialog dialog
  CBrowseFolderDialog(const CString &strHint = CString(), UINT nFlags = 0U,
          CWnd *pParentWnd = NULL,
          int nRootFolder = CSIDL_DESKTOP);
  /// Load the "hint" from Resource
  CBrowseFolderDialog(int nHint, UINT nFlags = 0U, CWnd *pParentWnd = NULL,
          int nRootFolder = CSIDL_DESKTOP);
  /// Construct a CBrowseFolderDialog dialog rooted at an arbitrary folder
  CBrowseFolderDialog(const CString &strHint, const CString &strRoot,
          UINT nFlags = 0U, CWnd *pParentWnd = NULL);
  /// Load the "hint" from Resource, but root the browse
  /// operation at an arbitrary folder
  CBrowseFolderDialog(int nHint, const CString &strRoot, UINT nFlags = 0U,
          CWnd *pParentWnd = NULL);

  // Attributes
public:
  /// Retrieve the display name of the selected item
  CString GetDisplayName() const;
  /// Retrieve the ITEMIDLIST of the selected item
  LPCITEMIDLIST GetItemIdList() const;
  /// Retrieve the path to the selected item
  CString GetPath() const;

  // Operations
public:
  /// Display the Dialog - returns IDOK or IDCANCEL
  int DoModal();
  /// En/Dis-able the "Ok" button
  void EnableOk(BOOL bEnable);
  /// Set the current selection in the tree control
  void SetSelection(LPCITEMIDLIST pItemIdList);
  /// Set the current selection in the tree control
  void SetSelection(const CString &strPath);
  /// Set the "hint" text
  void SetText(const CString &strNewText);

  // Overrides
public:
  /// Called when the BFF Dialog has initialized
  virtual void OnInitBFFDialog();
  /// Called when the selection has changed in the tree control
  virtual void OnBFFSelChanged(LPITEMIDLIST pNewSel);
  /// Called when the user types an invalid name
  virtual BOOL OnBFFValidateFailed(const CString &strBadName);

  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CBrowseFolderDialog)
  //}}AFX_VIRTUAL

  // Implementation
public:
  virtual ~CBrowseFolderDialog();

  // Generated message map functions
protected:
  //{{AFX_MSG(CBrowseFolderDialog) NOTE - the ClassWizard will add and remove
  // member functions here.
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()

private:
  /// Static method to be used for the SHBFF callback
  static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT nMsg,
                                         LPARAM lParam,
                                         LPARAM lpData);

private:
  /// Free the memory referenced by m_pItemIdList
  void FreeItemIdList(IMalloc *pMalloc = NULL);
  /// CSIDL => ITEMIDLIST
  LPITEMIDLIST ResolveCsidl(int nCsidl) const;
  /// Textual filesystem path => ITEMIDLIST
  LPITEMIDLIST ResolveFsPath(const CString &strPath) const;

private:
  /// Display name of the selected item
  CString m_strDisplayName;
  /// Flags to be passed to the browse dialog
  UINT m_nFlags;
  /// "Hint" to be displayed above the tree control
  CString m_strHint;
  /// ITEMIDLIST identifying the selected Shell item
  LPITEMIDLIST m_pItemIdList;
  /// Parent CWnd (NULL => App main window)
  CWnd *m_pParentWnd;
  /// Selected path
  CString m_strPath;
  /// ITEMIDLIST identifying the root
  LPITEMIDLIST m_pRoot;


};


/////////////////////////////////////////////////////////////////


#ifndef _DEBUG
inline CString CBrowseFolderDialog::GetDisplayName() const
{ return m_strDisplayName; }

inline LPCITEMIDLIST CBrowseFolderDialog::GetItemIdList() const
{ return m_pItemIdList; }

inline CString CBrowseFolderDialog::GetPath() const
{ return m_strPath; }
#endif  // not _DEBUG


//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations im-
// mediately before the previous line.

//}}AFX_STOP_SYNTAX_HIGHLIGHTING


// Local Variables:
// fill-column: 65
// indent-tabs-mode: nil
// show-trailing-whitespace: t
// End:

#endif // BROWSEFOLDERDIALOG_H_97B5E754_8072_4B62_8278_410436D5A2D8
